#ifndef __UTILS_H__
#define __UTILS_H__

#include <linux/kernel.h>

//ar_misc_ctrl
#define AUTOPM_DISABLE  0x1

/** module bitmap for dbg print */
extern uint ar_dbg_mod;
/** Debug level for dbg print */
extern uint ar_dbg_lv;
/** Misc control such as pm */
extern u8 ar_misc_ctrl;

/* control the debug chardev module */
extern u8 ar_dbg_mod_chardev;
/* control the debug chardev level */
extern u8 ar_dbg_lv_chardev;
/* Whether enable the debug chardev*/
extern int ar_dbg_chardev_enable;

#define AR_LOG    "[AR] "

enum {
    DM_NONE = 0x00,
    DM_RPC  = 0x01,   /* artosyn rpc log flag */
    DM_USB  = 0x02,   /* artosyn usb log flag */
    DM_RX   = 0x04,   /* artosyn RX DUMP flag */
    DM_TX   = 0x08,   /* artosyn TX DUMP flag */
    DM_NET_DEV = 0x10,   /* artosyn net device flag */
    DM_GENERIC = 0x20,   /* artosyn generic log flag */
    DM_PKTDUMP = 0x40,   /* pkt dump flag */
    DM_PROC  = 0x80,   /* artosyn proc log flag */
    DM_DNLD  = 0x100,   /* artosyn firmware download flag */
    DM_CDEV  = 0x200,   /* artosyn char dev flag */
    DM_SDIO  = 0x400,   /* artosyn sdio log flag */
    DM_ANY  = 0xFFFF
};
#define AR_DEBUG_ALL (DM_RPC | DM_USB | DM_SDIO | DM_RX | DM_TX | DM_GENERIC | DM_NET_DEV | DM_PKTDUMP | DM_PROC | DM_CDEV | DM_DNLD)

#define AR_FN_ENTRY_STR "--> %s()\n", __func__
#define AR_FN_LEAVE_STR "<-- %s()\n", __func__

enum dbg_sev_tag
{
    DL_NONE = 0,
    DL_OOPS,
    DL_ERR,
    DL_MSG,
    DL_WRN,
    DL_INF,
    DL_VRB,
    DL_MAX
};

#define DEFAULT_DEBUG_LVL DL_WRN

typedef enum {
    ROM_VER_CMD_FAIL,
    RUNTIME_CMD_FAIL,
    FW_DOWNLOAD_START_CMD_FAIL,
    FW_DOWNLOAD_MEM_ALLOC_FAIL,
    FW_DOWNLOAD_CMD_FAIL,
    FW_DOWNLOAD_END_CMD_FAIL,
    FW_GET_STATE_CMD_FAIL,
    FW_GET_STATE_FAIL,
    FW_REQUEST_FAIL,
    FW_NOT_READY,
    URB_INIT_FAIL,
    IPC_ALLOC_FAIL,
    UDEV_ALLOC_FAIL,
    USB_EP_NUM_ERROR,
    USB_CONFIG_ERROR,
    CMD_TIMEOUT,
    MEM_ALLOC_FAIL,
    AR_ERROR_MAX
} AR_ERROR_E;

#define AR_DBG(m, lv, fmt, ...) do {                                        \
    if (ar_dbg_chardev_enable &&                                            \
        ((ar_dbg_mod_chardev & (m)) && (ar_dbg_lv_chardev & BIT(lv)))) {    \
        /*ar_dbg_chardev_printf(fmt, ##__VA_ARGS__);*/                        \
    }                                                                       \
    if ((ar_dbg_mod & (m)) && ((ar_dbg_lv >= (lv)))) {                      \
        printk("[artosyn_drv] "fmt, ##__VA_ARGS__);                                         \
    }                                                                       \
    if (lv == DL_OOPS)                                                      \
        BUG();                                                              \
} while (0)

#define AR_ERROR(error_code)                          \
    {                                                 \
        printk("##################################################\n"); \
        printk("##### CRITICAL ERROR : %s #####\n", #error_code);       \
        printk("##################################################\n"); \
    }

#define HERE() do{printk("[artosyn_drv] %s %d\n", __FUNCTION__,__LINE__);}while(0);


/** Log entry point for debugging */
#define ENTER()         AR_DBG(DM_GENERIC, DL_INF, AR_FN_ENTRY_STR);
/** Log exit point for debugging */
#define LEAVE()         AR_DBG(DM_GENERIC, DL_INF, AR_FN_LEAVE_STR);

#ifndef MIN
/** Find minimum */
#define MIN(a, b)        ((a) < (b) ? (a) : (b))
#endif

/** Find maximum */
#ifndef MAX
#define MAX(a, b)                ((a) > (b) ? (a) : (b))
#endif

/** IN parameter */
#define IN
/** OUT parameter */
#define OUT

/**
 *  @brief      Dump the data in hex
 *
 *  @param      lvl  Debug level to print, refers to DL_xxx
 *  @param      note Dump message
 *  @param      data Data to print
 *  @param      len  Length of the data
 *
 *  @return     N/A
 */
void dump_bytes(uint lvl, char *note, u8 *data, int len);

#endif